package com.cstar.learnlang.RestControllers;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

import com.cstar.learnlang.DataForms.NewVocabularyListDataForm;
import com.cstar.learnlang.DataForms.SearchVocabularyListDataForm;
import com.cstar.learnlang.PageControllers.HomePageController;
import com.cstar.learnlang.PageControllers.VocabularyPageController;
import com.cstar.learnlang.RowMappers.UserVocListRowMapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

@Controller
@RequestMapping(value={"", "/vocabularyPage/vocListSearch", "/vocabularyPage/vocList/{rowId}"})
@SessionAttributes
public class VocListRestController {
	private static final Logger logger = LoggerFactory.getLogger(VocListRestController.class);
	@Autowired private JdbcTemplate jdbcRegisterInfoTemplate;
	@Autowired private HomePageController homePageController;
	@Autowired private VocabularyPageController vocPageController;
	
	@RequestMapping(value="/vocabularyPage/vocListSearch", method = RequestMethod.POST)
    public ModelAndView vocListSearch(
    		HttpServletRequest request,
			@RequestParam (value="pageSize", required=false) String pageSize,
			@RequestParam (value="pageIdx", required=false) String pageIdx, // pageIdx is one based
    		@RequestParam(value="s_tags", required=false) String tags, 
    		@RequestParam(value="s_words", required=false) String words, 
    		@RequestParam(value="fromLang", required=false) String from, 
    		@RequestParam(value="toLang", required=false) String to, 
    		@ModelAttribute("searchVocabularyListInfo") SearchVocabularyListDataForm searchVocabularyListInfo, 
    		BindingResult result) {
		HttpSession session = request.getSession();
		tags = homePageController.null2Empty(tags);
		words = homePageController.null2Empty(words);
		from = homePageController.null2Empty(from);
		pageSize = homePageController.null2Empty(pageSize);
		pageIdx = homePageController.null2Empty(pageIdx);
		to = homePageController.null2Empty(to);
		logger.info("vocListSearch: tags:{} words:{} from:{} to:{} pageIdx:{}", new String[] {tags, words, from, to, pageIdx});
		ModelAndView mv = new ModelAndView ("/vocabularyPage");
		searchVocabularyListInfo.setTags(tags);
		searchVocabularyListInfo.setPageSize(pageSize);
		searchVocabularyListInfo.setPageIdx(pageIdx);
		searchVocabularyListInfo.setWords(words);
		searchVocabularyListInfo.setFromLang(from);
		searchVocabularyListInfo.setToLang(to);
		searchVocabularyListInfo.setLangMap(VocabularyPageController.langMap);
		mv.getModelMap().addAttribute("searchVocabularyListInfo", searchVocabularyListInfo); // return search criteria
		session.setAttribute("searchVocabularyListInfo", searchVocabularyListInfo); // set search criteria
        mv = vocPageController.populatePageModel (session, mv);
        @SuppressWarnings("unchecked")
		List<NewVocabularyListDataForm> rs = (List<NewVocabularyListDataForm>)mv.getModelMap().get("searchResList");
		if (rs == null || rs.size() == 0) {
			session.setAttribute("serverReturnCode", "Error:No vocabulary is found");
			rs = new ArrayList<NewVocabularyListDataForm>(); 
		} // if
		logger.info("vocListSearch size:{} sid:{} leftnav:{}", new String[] {new Integer(rs.size()).toString(), session.getId(), "4"});
		session.setAttribute("leftNavItemIdx", "4");
		return mv;
    } // vocListSearch
	@RequestMapping(value = "/vocabularyPage/vocList/{rowId}", method = RequestMethod.GET)
	@ResponseBody
	public NewVocabularyListDataForm vocListGet(
			HttpServletRequest request,
			HttpSession session,
			@PathVariable String rowId) {
		logger.info("vocListGet rowId:{}", new String[] {rowId});
		String sql = "SELECT * FROM VOCABULARY_LIST WHERE id = ?";
		@SuppressWarnings("unchecked")
		List<NewVocabularyListDataForm> rs = jdbcRegisterInfoTemplate.query(sql, new Object[] {rowId}, new UserVocListRowMapper());
		if (rs.size() == 0) {
			return new NewVocabularyListDataForm();
		} // if
		return rs.get(0);
	} // vocListGet
	@RequestMapping(value = "/vocabularyPage/vocList/{rowId}", method = RequestMethod.PUT)
	public ModelAndView vocListUpdate(
			HttpServletRequest request,
			HttpSession session,
			@PathVariable String rowId,
			@RequestBody NewVocabularyListDataForm newVoc) {
		ModelAndView mv = new ModelAndView ("redirect:/vocabularyPage");
		logger.info("vocListUpdate id: {}, name:{}", new String[] {rowId, newVoc.getName()});
		String sql = "UPDATE VOCABULARY_LIST SET name=?, tags=?, from_lang=?, to_lang=?, words=?, from_lang_text=?, to_lang_text=? WHERE id = ?";
		jdbcRegisterInfoTemplate.update(sql, new Object[] {
				newVoc.getName(),
				newVoc.getTags(),
				newVoc.getFromLang(),
				newVoc.getToLang(),
				newVoc.getWordsList(),
				newVoc.getFromLangText(),
				newVoc.getToLangText(),
				rowId
			});
		session.setAttribute("serverReturnCode", "Success:Vocabulary is updated");
		session.setAttribute("leftNavItemIdx", "2");
		return vocPageController.populatePageModel (session, mv);
	} // vocListUpdate
	@RequestMapping(value = "/vocabularyPage/vocList/{rowId}", method = RequestMethod.DELETE)
	public ModelAndView vocListDelete(
			HttpServletRequest request,
			HttpServletResponse response,
			HttpSession session,
			@PathVariable String rowId) {
		String userid = (String)session.getAttribute("userid");
		logger.info("vocListDelete id: {}", new String[] {rowId});
		ModelAndView mv = new ModelAndView ("redirect:/vocabularyPage");
		// First check if this vocabulary is added as favorite by another user
		boolean inFav = jdbcRegisterInfoTemplate.queryForInt("SELECT COUNT(*) FROM SAVED_VOCABULARY_LISTS WHERE VOCLIST_ID = ?", new Object[] {rowId}) != 0;
		if (inFav) { // update user_id of vocabulary list so that it does not show up manage vocabulary list. 
			jdbcRegisterInfoTemplate.update ("UPDATE VOCABULARY_LIST SET USER_ID=0 WHERE ID=?", new Object[]{rowId});
		} else { // We can simply delete the row.
			String sql = "DELETE FROM VOCABULARY_LIST WHERE id = ? AND user_Id = ?";
			jdbcRegisterInfoTemplate.update(sql, new Object[] {rowId, userid});
		} // if
		session.setAttribute("serverReturnCode", "Success:Selected vocabulary is deleted");
		session.setAttribute("leftNavItemIdx", "2");
		return vocPageController.populatePageModel (session, mv);
	} // vocListDelete
	@RequestMapping(value="/vocabularyPage/vocList", method = RequestMethod.POST)
    public ModelAndView vocListCreate(
    		HttpServletRequest request,
    		@ModelAttribute("newVocabularyListInfo") NewVocabularyListDataForm newVocabularyListInfo, 
    		BindingResult result) {
		HttpSession session = request.getSession();
		logger.info("vocListCreate");
		String sql;
		ModelAndView mv = new ModelAndView ("redirect:/vocabularyPage");
		sql = "INSERT INTO VOCABULARY_LIST (USER_ID, NAME, TAGS, WORDS, FROM_LANG, "+
				"TO_LANG, FROM_LANG_TEXT, TO_LANG_TEXT) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
		jdbcRegisterInfoTemplate.update(sql, new Object[] { 
			(String)session.getAttribute("userid"),
			newVocabularyListInfo.getName(),
			newVocabularyListInfo.getTags(),
			newVocabularyListInfo.getWordsList(),
			newVocabularyListInfo.getFromLang(),
			newVocabularyListInfo.getToLang(),
			VocabularyPageController.langMap.get(newVocabularyListInfo.getFromLang()),
			VocabularyPageController.langMap.get(newVocabularyListInfo.getToLang())
		});
		session.setAttribute("serverReturnCode", "Success:New vocabulary list is created");
		session.setAttribute("leftNavItemIdx", "2");
		logger.info("newVocabularyListPost sid:{} leftnav:{}", new String[] {session.getId(), "2"});
		return vocPageController.populatePageModel (session, mv);
    } // vocListCreate
	@ModelAttribute("searchFavVocListInfo")
    public SearchVocabularyListDataForm searchFavVocListInfo() {
		SearchVocabularyListDataForm data = new SearchVocabularyListDataForm();
		data.setLangMap(VocabularyPageController.langMap);
        return data;
    } // searchFavVocListInfo
	@ModelAttribute("searchVocabularyListInfo")
    public SearchVocabularyListDataForm searchVocabularyListInfo() {
		SearchVocabularyListDataForm data = new SearchVocabularyListDataForm();
		data.setLangMap(VocabularyPageController.langMap);
        return data;
    } // searchVocabularyListInfo
	@ModelAttribute("newVocabularyListInfo")
    public NewVocabularyListDataForm newVocabularyListInfo() {
        return new NewVocabularyListDataForm();
    } // newVocabularyListInfo
} // VocListRestController
